/*
 *    Copyright (c) 2018-2025, cloud All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: cloud
 */
package com.fuyao.cloud.asset.warehous.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fuyao.cloud.admin.api.feign.RemoteDeptService;
import com.fuyao.cloud.asset.card.service.AssetAssetcardService;
import com.fuyao.cloud.asset.constant.AssetConstant;
import com.fuyao.cloud.asset.constant.WarehousConstant;
import com.fuyao.cloud.asset.contract.service.AssetContractService;
import com.fuyao.cloud.asset.dto.warehous.WarehousCreateDTO;
import com.fuyao.cloud.asset.dto.warehous.WarehousEditDTO;
import com.fuyao.cloud.asset.dto.warehous.WarehousSearchDTO;
import com.fuyao.cloud.asset.entity.AssetCard;
import com.fuyao.cloud.asset.entity.AssetContract;
import com.fuyao.cloud.asset.entity.AssetSupplier;
import com.fuyao.cloud.asset.entity.ac.AssetAc;
import com.fuyao.cloud.asset.entity.warehous.Warehous;
import com.fuyao.cloud.asset.entity.warehous.WarehousList;
import com.fuyao.cloud.asset.enums.AssetStatusEnum;
import com.fuyao.cloud.asset.enums.CardStatusEnum;
import com.fuyao.cloud.asset.supplier.service.AssetSupplierService;
import com.fuyao.cloud.asset.vo.warehous.WarehousExcelVO;
import com.fuyao.cloud.asset.vo.warehous.WarehousPageVO;
import com.fuyao.cloud.asset.vo.warehous.WarehousSellExcelVO;
import com.fuyao.cloud.asset.warehous.mapper.WarehousMapper;
import com.fuyao.cloud.asset.warehous.service.WarehousService;
import com.fuyao.cloud.asset.warehouslist.service.WarehousListService;
import com.fuyao.cloud.common.core.constant.CommonConstants;
import com.fuyao.cloud.common.core.model.BaseEntity;
import com.fuyao.cloud.common.core.util.DictItemOption;
import com.fuyao.cloud.common.core.util.R;
import com.fuyao.cloud.common.data.datascope.DataScope;
import com.fuyao.cloud.common.data.resolver.DictItemResolver;
import com.fuyao.cloud.common.data.resolver.NumberResolver;
import com.fuyao.cloud.common.data.resolver.ParamResolver;
import com.fuyao.cloud.common.security.service.CloudUser;
import com.fuyao.cloud.common.security.util.SecurityUtils;
import com.fuyao.cloud.space.entity.RoomHouse;
import com.fuyao.cloud.space.entity.RoomPosition;
import com.fuyao.cloud.space.house.service.RoomHouseService;
import com.fuyao.cloud.space.position.service.RoomPositionService;
import com.fuyao.cloud.space.vo.PositionVO;
import lombok.AllArgsConstructor;
import org.apache.commons.compress.utils.Lists;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 入库管理
 *
 * @author liyue
 * @date 2021-12-06 20:19:22
 */
@Service
@AllArgsConstructor
public class WarehousServiceImpl extends ServiceImpl<WarehousMapper, Warehous> implements WarehousService {

    private final AssetContractService contractService;
    private final AssetSupplierService supplierService;
    private final RemoteDeptService deptService;
    private final RoomHouseService houseService;
    private final RoomPositionService positionService;
    private final WarehousListService warehousListService;
    private final AssetAssetcardService assetcardService;

    @Transactional
    @Override
    public boolean save(Warehous entity) {
        setFieldValue(entity);
        boolean save = super.save(entity);
        if(save){
            this.warehousListService.saveOrUpdateWarehousList(entity);
        }
        return save;
    }

    @Transactional
    @Override
    public boolean updateById(Warehous entity) {
        setFieldValue(entity);
        boolean update = super.updateById(entity);
        if(update){
            this.warehousListService.saveOrUpdateWarehousList(entity);
        }
        return update;
    }

    @Override
    public List listWarehous(QueryWrapper<Warehous> query, String classify) {
        List<Warehous> warehousList = this.baseMapper.selectListByScope(query, new DataScope());
        Map<String, List<DictItemOption>> resultMap = DictItemResolver.getDictOptionResultMap(WarehousConstant.DICT_OPTION_TYPES);
        if (CollUtil.isNotEmpty(warehousList)) {
            if ("0".equals(classify)) {
                // 入库
                return warehousList.stream().map(ware -> {
                    WarehousExcelVO excelVO = new WarehousExcelVO();
                    BeanUtil.copyProperties(ware, excelVO);
                    excelVO.setStatus(DictItemResolver.getDictOptionLabel(resultMap.get(WarehousConstant.WAREHOUS_STATUS), String.valueOf(ware.getStatus())));
                    excelVO.setType(DictItemResolver.getDictOptionLabel(resultMap.get(AssetConstant.TYPE_DOCUMENT), String.valueOf(ware.getType())));
                    return excelVO;
                }).collect(Collectors.toList());
            } else {
                // 冲销
                return warehousList.stream().map(ware -> {
                    WarehousSellExcelVO excelVO = new WarehousSellExcelVO();
                    BeanUtil.copyProperties(ware, excelVO);
                    excelVO.setStatus(DictItemResolver.getDictOptionLabel(resultMap.get(WarehousConstant.WAREHOUS_STATUS), String.valueOf(ware.getStatus())));
                    excelVO.setType(DictItemResolver.getDictOptionLabel(resultMap.get(AssetConstant.TYPE_DOCUMENT), String.valueOf(ware.getType())));
                    return excelVO;
                }).collect(Collectors.toList());
            }
        }
        return Lists.newArrayList();
    }

    @Override
    public WarehousCreateDTO create(String classify) {
        WarehousCreateDTO createDTO = new WarehousCreateDTO();
        // 可选项和树
        CloudUser user = SecurityUtils.getUser();
        createDTO.setCreateId(user.getId());
        createDTO.setCreateBy(user.getName());
        createDTO.setCreateTime(LocalDateTimeUtil.now());
        createDTO.setUnid(UUID.randomUUID().toString());
        createDTO.setStatus(WarehousConstant.WAREHOUS_DEFAULT_STATUS);
        createDTO.setCurrencyType(WarehousConstant.WAREHOUS_DEFAULT_CURRENCY_TYPE);
        createDTO.setDetailed(StrUtil.EMPTY);
        createDTO.setType(WarehousConstant.WAREHOUS_DEFAULT_TYPE);
        createDTO.setDeptId(user.getDeptId());
        createDTO.setDeptFullname(user.getFullName());
        createDTO.setDictOption(getDictOption());
        createDTO.setClassify(classify);

        String caseKey = ParamResolver.getStr("CIS_CASE_VALUE", "CIS");
        if (WarehousConstant.WAREHOUS_CLASSIFY_1.equals(createDTO.getClassify())) {
            caseKey = ParamResolver.getStr("CAI_CASE_VALUE", "CAI");
        }
        Map<String, String> numberMap = NumberResolver.getNumberMap(WarehousConstant.WAREHOUS_NUMBER_TYPE, DateUtil.format(new Date(), DatePattern.SIMPLE_MONTH_PATTERN), 5L).getData();
        createDTO.setCaseid(caseKey + DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN) + numberMap.get("code"));
        return createDTO;
    }

    @Override
    public WarehousEditDTO edit(Long id) {
        Warehous warehous = this.getById(id);
        Assert.isTrue(ObjectUtils.isNotEmpty(warehous), String.format("%s不合法", id));
        WarehousEditDTO editDTO = new WarehousEditDTO();
        BeanUtil.copyProperties(warehous, editDTO);
        editDTO.setDictOption(getDictOption());
        // 加载明细。
        List<WarehousList> warehousLists = this.warehousListService.getBaseMapper().selectList(Wrappers.<WarehousList>query().lambda().eq(WarehousList::getWarehousId, id));
        editDTO.setWarehousList(warehousLists);
        return editDTO;
    }

    @Override
    public IPage<Warehous> page(Page page, QueryWrapper queryWrapper, WarehousSearchDTO searchDTO) {
        queryWrapper.eq("del_flag", 0);
        return this.baseMapper.page(page, queryWrapper, searchDTO, new DataScope());
    }

    @Override
    public R batchDelete(List<Long> ids) {
        List<Warehous> warehousList = this.list(Wrappers.<Warehous>query().lambda().in(BaseEntity::getId, ids));
        if (CollUtil.isEmpty(warehousList)) {
            return R.failed("未找到相应的入库单数据");
        }
        CloudUser user = SecurityUtils.getUser();
        boolean allMatch = warehousList.stream().allMatch(purchaseorder -> AssetStatusEnum.DRAFT.getCode().equals(purchaseorder.getStatus()) && user.getId().equals(purchaseorder.getCreateId()));
        if (!allMatch) {
            return R.failed("只能删除草稿状态且创建用户为当前用户的入库单数据");
        }
        boolean remove = this.warehousListService.remove(Wrappers.<WarehousList>query().lambda().in(WarehousList::getParentId, ids));
        boolean delete = this.removeBatchByIds(ids);
        if (!delete && !remove) {
            return R.failed("删除失败，请检查数据有效性");
        }
        return R.ok(CommonConstants.SUCCESS, "删除成功");
    }

    @Transactional
    @Override
    public boolean generateByWarehouse(AssetAc assetAc,List<AssetCard> assetCardList) {
        Warehous warehous = new Warehous();
        BeanUtil.copyProperties(assetAc, warehous);
        warehous.setType(assetAc.getType());
        warehous.setClassify(WarehousConstant.WAREHOUS_CLASSIFY_0);
        warehous.setStatus(AssetStatusEnum.FINISH.getCode());
        warehous.setParentId(assetAc.getId());
        warehous.setParentCaseid(assetAc.getCaseid());
        warehous.setBatchnumber(assetAc.getBatchnumber());
        warehous.setCaseid(null);
        warehous.setId(null);
        // 存放地点全名称
        if (null != assetAc.getLocationId() && assetAc.getLocationId() > 0) {
            PositionVO positionVO = positionService.getPositionById(assetAc.getLocationId());
            warehous.setFullLocation(positionVO.getFullLocation());
        }
        boolean save = this.save(warehous);
        if (save) {
            return warehousListService.saveOrUpdateWarehousList(warehous, assetAc, assetCardList);
        }
        return false;
    }

    @Override
    public IPage<WarehousPageVO> getWarehousPage(Page page, QueryWrapper query, WarehousSearchDTO searchDTO) {
        query.eq("del_flag",0);
        return this.baseMapper.getWarehousPage(page,query,searchDTO);
    }

    @Override
    public void classifyAssetCard(Warehous warehous) {
        List<WarehousList> warehousLists = this.warehousListService.list(Wrappers.<WarehousList>query().lambda().eq(WarehousList::getWarehousId, warehous.getId()));
        List<Long> ids = warehousLists.stream().map(WarehousList::getAssetCardId).collect(Collectors.toList());
        this.assetcardService.updateStatus(ids, CardStatusEnum.OFFSET.getCode());
    }

    private WarehousEditDTO.DictOption getDictOption() {
        // 可选项和树
        Map<String, List<DictItemOption>> resultMap = DictItemResolver.getDictOptionResultMap(WarehousConstant.DICT_OPTION_TYPES);
        WarehousCreateDTO.DictOption dictOption = new WarehousCreateDTO.DictOption();
        dictOption.setStatusList(resultMap.get(WarehousConstant.WAREHOUS_STATUS));
        dictOption.setPurchaseWayList(resultMap.get(AssetConstant.PURCHASE_WAY));
        dictOption.setCurrencyTypeList(resultMap.get(AssetConstant.CURRENCY_TYPE));
        dictOption.setContractTreeList(contractService.selectContractTree(Wrappers.query(new AssetContract())));
        AssetSupplier fyAssetSupplier = new AssetSupplier();
        fyAssetSupplier.setType("V");
        dictOption.setSupplierTreeList(supplierService.selectTree(Wrappers.query(fyAssetSupplier)));
        dictOption.setDeptTreeList(deptService.tree().getData());
        dictOption.setHouseTreeList(houseService.selectTree());
        dictOption.setPositionTreeList(positionService.selectTree(Wrappers.query(new RoomPosition())));
        return dictOption;
    }

    private void setFieldValue(Warehous entity) {
        // 补充金额和清单信息
        List<WarehousList> warehousList = entity.getWarehousList();
        if (CollUtil.isNotEmpty(warehousList)) {
            StringBuilder detailed = new StringBuilder();
            warehousList.forEach(p -> detailed.append(p.getName()).append(","));
            detailed.deleteCharAt(detailed.length() - 1);
            // 计算总金额
            long amount = warehousList.stream().collect(Collectors.summarizingLong((WarehousList::getAmountLong))).getSum();
            entity.setAmount(new BigDecimal(amount));
            entity.setDetailed(detailed.toString());
        }
        String caseKey = ParamResolver.getStr("CIS_CASE_VALUE", "CIS");
        if (WarehousConstant.WAREHOUS_CLASSIFY_1.equals(entity.getClassify())) {
            caseKey = ParamResolver.getStr("CAI_CASE_VALUE", "CAI");
        }
        if (StrUtil.isEmpty(entity.getCaseid())) {
            Map<String, String> numberMap = NumberResolver.getNumberMap(WarehousConstant.WAREHOUS_NUMBER_TYPE, DateUtil.format(new Date(), DatePattern.SIMPLE_MONTH_PATTERN), 5L).getData();
            entity.setCaseid(caseKey + DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN) + numberMap.get("code"));
        }
        if (StrUtil.isEmpty(entity.getBatchnumber())) {
            CloudUser user = SecurityUtils.getUser();
            String batchNumber = NumberResolver.getCodeByDateTime(caseKey, user.getId(), 5);
            entity.setBatchnumber(batchNumber);
        }
        if (ObjectUtils.isNotEmpty(entity.getContractId()) && entity.getContractId() > 0) {
            AssetContract contract = this.contractService.getById(entity.getContractId());
            entity.setContractName(contract.getName());
            entity.setContractNumber(contract.getContractId());
        }
        if (ObjectUtils.isNotEmpty(entity.getSupplierId()) && entity.getSupplierId() > 0) {
            AssetSupplier supplier = this.supplierService.getById(entity.getSupplierId());
            entity.setSupplierName(supplier.getName());
        }
        if (ObjectUtils.isNotEmpty(entity.getHouseId()) && entity.getHouseId() > 0) {
            RoomHouse roomHouse = this.houseService.getById(entity.getHouseId());
            entity.setHouseName(roomHouse.getName());
            entity.setFullLocation(roomHouse.getParentFullname() + "." + roomHouse.getName());
        }
        if (ObjectUtils.isNotEmpty(entity.getLocationId()) && entity.getLocationId() > 0) {
            PositionVO positionVO = this.positionService.getPositionById(entity.getLocationId());
            entity.setLocationName(positionVO.getName());
            entity.setFullLocation(positionVO.getFullLocation());
        }
    }
}
